#ifndef __MATH_H__
#define __MATH_H__

#include <go/math_go.h>

#define M_E         math.E
#define M_LOG2E     math.Log2E
#define M_LOG10E    math.Log10E
#define M_LN2       math.Ln2
#define M_LN10      math.Ln10
#define M_PI        math.Pi
#define M_PI_2      (M_PI / 2)
#define M_PI_4      (M_PI / 4)
#define M_1_PI      (1 / M_PI)
#define M_2_PI      (2 / M_PI)
#define M_2_SQRTPI  (2 / math.SqrtPi)
#define M_SQRT2     math.Sqrt2
#define M_SQRT1_2   (M_SQRT2 / 2)

#define abs(x)   (int)math.Abs(x)
#define labs(x)  (long)math.Abs(x)
#define llabs(x) (long long)math.Abs(x)
#define fabsf(x) math.Abs(x)
#define fabsl(x) math.Abs(x)
#define fabs(x)  math.Abs(x)

#define asinh(x)  math.Asinh(x)
#define asinhf(x) math.Asinh(x)
#define asinhl(x) math.Asinh(x)
#define acosh(x)  math.Acosh(x)
#define acoshf(x) math.Acosh(x)
#define acoshl(x) math.Acosh(x)
#define atanh(x)  math.Atanh(x)
#define atanhf(x) math.Atanh(x)
#define atanhl(x) math.Atanh(x)

#define asin(x)  math.Asin(x)
#define asinf(x) math.Asin(x)
#define asinl(x) math.Asin(x)
#define acos(x)  math.Acos(x)
#define acosf(x) math.Acos(x)
#define acosl(x) math.Acos(x)
#define atan(x)  math.Atan(x)
#define atanf(x) math.Atan(x)
#define atanl(x) math.Atan(x)
#define atan2(y, x)  math.Atan2(y, x)
#define atan2f(y, x) math.Atan2(y, x)
#define atan2l(y, x) math.Atan2(y, x)

#define sin(x)  math.Sin(x)
#define sinf(x) math.Sin(x)
#define sinl(x) math.Sin(x)
#define cos(x)  math.Cos(x)
#define cosf(x) math.Cos(x)
#define cosl(x) math.Cos(x)
#define tan(x)  math.Tan(x)
#define tanf(x) math.Tan(x)
#define tanl(x) math.Tan(x)
#define sincos(x, s, c)  math.Sincos(x, s, c)
#define sincosl(x, s, c) math.Sincos(x, s, c)
#define sincosf(x, s, c) math.Sincos(x, s, c)

#define sinh(x)  math.Sinh(x)
#define sinhf(x) math.Sinh(x)
#define sinhl(x) math.Sinh(x)
#define cosh(x)  math.Cosh(x)
#define coshf(x) math.Cosh(x)
#define coshl(x) math.Cosh(x)
#define tanh(x)  math.Tanh(x)
#define tanhf(x) math.Tanh(x)
#define tanhl(x) math.Tanh(x)

#define nan(tagp)  math.NaN()
#define nanf(tagp) math.NaN()
#define nanl(tagp) math.NaN()
#define isnan(x)   math.IsNaN(x)
#define isinf(x)   math.IsInf(x, 0)
#define signbit(x) math.Signbit(x)

#define sqrt(x)  math.Sqrt(x)
#define sqrtf(x) math.Sqrt(x)
#define sqrtl(x) math.Sqrt(x)
#define cbrt(x)  math.Cbrt(x)
#define cbrtf(x) math.Cbrt(x)
#define cbrtl(x) math.Cbrt(x)

#define copysign(f, sign)  math.Copysign(f, sign)
#define copysignf(f, sign) math.Copysign(f, sign)
#define copysignl(f, sign) math.Copysign(f, sign)

#define fdim(x, y)  math.Dim(x, y)
#define fdimf(x, y) math.Dim(x, y)
#define fdiml(x, y) math.Dim(x, y)
#define fmax(x, y)  math.Max(x, y)
#define fmaxf(x, y) math.Max(x, y)
#define fmaxl(x, y) math.Max(x, y)
#define fmin(x, y)  math.Min(x, y)
#define fminf(x, y) math.Min(x, y)
#define fminl(x, y) math.Min(x, y)

#define erf(x)   math.Erf(x)
#define erff(x)  math.Erf(x)
#define erfl(x)  math.Erf(x)
#define erfc(x)  math.Erfc(x)
#define erfcf(x) math.Erfc(x)
#define erfcl(x) math.Erfc(x)

#define exp(x)    math.Exp(x)
#define expf(x)   math.Exp(x)
#define expl(x)   math.Exp(x)
#define exp2(x)   math.Exp2(x)
#define exp2f(x)  math.Exp2(x)
#define exp2l(x)  math.Exp2(x)
#define expm1(x)  math.Expm1(x)
#define expm1f(x) math.Expm1(x)
#define expm1l(x) math.Expm1(x)

#define scalbn(x, n)   (x * math.Exp2(n))
#define scalbnf(x, n)  (x * math.Exp2(n))
#define scalbnl(x, n)  (x * math.Exp2(n))
#define scalbln(x, n)  (x * math.Exp2(n))
#define scalblnf(x, n) (x * math.Exp2(n))
#define scalblnl(x, n) (x * math.Exp2(n))

#define floor(x)  math.Floor(x)
#define floorf(x) math.Floor(x)
#define floorl(x) math.Floor(x)
#define ceil(x)   math.Ceil(x)
#define ceilf(x)  math.Ceil(x)
#define ceill(x)  math.Ceil(x)
#define trunc(x)  math.Trunc(x)
#define truncf(x) math.Trunc(x)
#define truncl(x) math.Trunc(x)

#define round(x)      math.Round(x)
#define roundf(x)     math.Round(x)
#define roundl(x)     math.Round(x)
#define lround(x)     (long)math.Round(x)
#define lroundf(x)    (long)math.Round(x)
#define lroundl(x)    (long)math.Round(x)
#define llround(x)    (long long)math.Round(x)
#define llroundf(x)   (long long)math.Round(x)
#define llroundl(x)   (long long)math.Round(x)
#define nearbyint(x)  math.Round(x)
#define nearbyintf(x) math.Round(x)
#define nearbyintl(x) math.Round(x)
#define rint(x)       math.Round(x)
#define rintf(x)      math.Round(x)
#define rintl(x)      math.Round(x)
#define lrint(x)      (long)math.Round(x)
#define lrintf(x)     (long)math.Round(x)
#define lrintl(x)     (long)math.Round(x)
#define llrint(x)     (long long)math.Round(x)
#define llrintf(x)    (long long)math.Round(x)
#define llrintl(x)    (long long)math.Round(x)

#define fma(x, y, z)  math.FMA(x, y, z)
#define fmaf(x, y, z) math.FMA(x, y, z)
#define fmal(x, y, z) math.FMA(x, y, z)

#define frexp(f, exp)     math.Frexp(f, exp)
#define frexpf(f, exp)    math.Frexp(f, exp)
#define frexpl(f, exp)    math.Frexp(f, exp)
#define ldexp(frac, exp)  math.Ldexp(frac, exp)
#define ldexpf(frac, exp) math.Ldexp(frac, exp)
#define ldexpl(frac, exp) math.Ldexp(frac, exp)

#define lgamma(x)  math.Gamma(x)
#define lgammaf(x) math.Gamma(x)
#define lgammal(x) math.Gamma(x)
#define tgamma(x)  math.Gamma(x)
#define tgammaf(x) math.Gamma(x)
#define tgammal(x) math.Gamma(x)

#define hypot(p, q)  math.Hypot(p, q)
#define hypotf(p, q) math.Hypot(p, q)
#define hypotl(p, q) math.Hypot(p, q)

#define log(x)    math.Log(x)
#define logf(x)   math.Log(x)
#define logl(x)   math.Log(x)
#define log1p(x)  math.Log1p(x)
#define log1pf(x) math.Log1p(x)
#define log1pl(x) math.Log1p(x)
#define log2(x)   math.Log2(x)
#define log2f(x)  math.Log2(x)
#define log2l(x)  math.Log2(x)
#define log10(x)  math.Log10(x)
#define log10f(x) math.Log10(x)
#define log10l(x) math.Log10(x)

#define logb(x)   math.Logb(x)
#define logbf(x)  math.Logb(x)
#define logbl(x)  math.Logb(x)
#define ilogb(x)  math.Ilogb(x)
#define ilogbf(x) math.Ilogb(x)
#define ilogbl(x) math.Ilogb(x)

#define fmod(x, y)  math.Mod(x, y)
#define fmodf(x, y) math.Mod(x, y)
#define fmodl(x, y) math.Mod(x, y)
#define modf(f, i)  math.Modf(f, i)
#define modff(f, i) math.Modf(f, i)
#define modfl(f, i) math.Modf(f, i)

#define nextafter(x, y)   math.Nextafter(x, y)
#define nextafterf(x, y)  math.Nextafter32(x, y)
#define nextafterl(x, y)  math.Nextafter(x, y)
#define nexttoward(x, y)  math.Nextafter(x, y)
#define nexttowardf(x, y) math.Nextafter32(x, y)
#define nexttowardl(x, y) math.Nextafter(x, y)

#define pow(x, y)  math.Pow(x, y)
#define powf(x, y) math.Pow(x, y)
#define powl(x, y) math.Pow(x, y)
#define pow10(n)   math.Pow10(n)

#define remainder(x, y)  math.Remainder(x, y)
#define remainderf(x, y) math.Remainder(x, y)
#define remainderl(x, y) math.Remainder(x, y)
#define remquo(x, y, quot)  (*(quot) = (int)((x) / (y)), math.Remainder(x, y))
#define remquof(x, y, quot) remquo(x, y, quot)
#define remquol(x, y, quot) remquo(x, y, quot)

#endif
